/**
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 *
 * 基于人眼视觉感知的自适应帧率控制器
 * 
 * 实现方式：跳过帧（Skip Frame）
 * - 始终以60fps调度，保证动画时间准确
 * - 根据目标帧率跳过部分帧的渲染
 * - 动画持续时间不变，只减少渲染次数
 *
 * @flow strict-local
 * @format
 */

'use strict';

import {
  FRAME_RATES,
  THRESHOLDS,
  HYSTERESIS,
  getDefaultConfig,
} from './FrameRateConfig';

import type {ThresholdConfig} from './FrameRateConfig';

type PropertyHistory = {|
  value: number,
  velocity: number,
  lastTime: number,
|};

export type PropertyType = 'opacity' | 'translate' | 'scale' | 'rotate';

type ControllerConfig = {|
  propertyType?: PropertyType,  // 属性类型，用于选择对应阈值
  frameRates?: {|
    HIGH?: number,
    MID?: number,
    LOW?: number,
  |},
  thresholds?: {|
    opacity?: ThresholdConfig,
    translate?: ThresholdConfig,
    scale?: ThresholdConfig,
    rotate?: ThresholdConfig,
  |},
  hysteresis?: {|
    stableFramesRequired?: number,
    immediateUpgrade?: boolean,
    enableDebugLog?: boolean,
  |},
|};

/**
 * 基于人眼视觉感知的自适应帧率控制器
 * 
 * 采用"跳过帧"策略：
 * - 60fps：每帧渲染（跳过0帧）
 * - 30fps：每2帧渲染一次（跳过1帧）
 * - 15fps：每4帧渲染一次（跳过3帧）
 * 
 * 优势：动画时间精确，不会延长
 */
export default class PerceptualFrameRateController {
  _frameRates: typeof FRAME_RATES;
  _thresholds: typeof THRESHOLDS;
  _hysteresis: typeof HYSTERESIS;
  _propertyType: PropertyType;  // 当前属性类型
  
  _history: PropertyHistory | null;
  _currentFrameRate: number;
  _stableCount: number;
  _pendingFrame: AnimationFrameID | null;
  
  // 跳帧相关状态
  _frameCounter: number;        // 帧计数器
  _skipInterval: number;        // 跳帧间隔（1=不跳，2=隔1帧，4=隔3帧）
  _lastRenderValue: number;     // 上次渲染的值
  _totalFrameCount: number;     // 总帧数计数（用于启动保护）

  constructor(config?: ControllerConfig) {
    const defaultConfig = getDefaultConfig();
    
    this._propertyType = config?.propertyType ?? 'translate';
    
    this._frameRates = {
      ...defaultConfig.frameRates,
      ...config?.frameRates,
    };
    
    this._thresholds = {
      ...defaultConfig.thresholds,
      ...config?.thresholds,
    };
    
    this._hysteresis = {
      ...defaultConfig.hysteresis,
      ...config?.hysteresis,
    };
    
    this._history = null;
    this._currentFrameRate = this._frameRates.HIGH;
    this._stableCount = 0;
    this._pendingFrame = null;
    
    // 初始化跳帧状态
    this._frameCounter = 0;
    this._skipInterval = 1;  // 1表示不跳帧
    this._lastRenderValue = 0;
    this._totalFrameCount = 0;  // 启动保护计数器
  }

  /**
   * 获取高精度时间戳
   * 优先使用 performance.now()，fallback 到 Date.now()
   */
  _getTimestamp(): number {
    if (typeof performance !== 'undefined' && performance.now) {
      return performance.now();
    }
    return Date.now();
  }

  /**
   * 获取当前属性类型对应的阈值配置
   */
  _getThreshold(): ThresholdConfig {
    return this._thresholds[this._propertyType] ?? this._thresholds.translate;
  }

  /**
   * 设置属性类型（运行时动态切换）
   */
  setPropertyType(propertyType: PropertyType): void {
    this._propertyType = propertyType;
  }

  /**
   * 计算属性变化速度
   * 
   * 优化：
   * 1. 使用 performance.now() 提高时间精度
   * 2. 忽略时间间隔过短的帧（避免除法误差）
   */
  _calculateVelocity(currentValue: number): number {
    const now = this._getTimestamp();
    const threshold = this._getThreshold();
    
    if (this._history === null) {
      this._history = {
        value: currentValue,
        velocity: threshold.HIGH_VELOCITY,
        lastTime: now,
      };
      return threshold.HIGH_VELOCITY;
    }
    
    const deltaTime = (now - this._history.lastTime) / 1000;
    
    // 忽略时间间隔过短的帧（小于5ms），避免除法导致的极端值
    if (deltaTime < 0.005) {
      return this._history.velocity;
    }
    
    const deltaValue = Math.abs(currentValue - this._history.value);
    const velocity = deltaValue / deltaTime;
    
    this._history = {
      value: currentValue,
      velocity: velocity,
      lastTime: now,
    };
    
    return velocity;
  }

  /**
   * 根据速度确定目标帧率
   * 
   * 直接根据速度阈值判断：
   * - 速度 >= HIGH_VELOCITY → 60fps
   * - 速度 >= LOW_VELOCITY → 30fps
   * - 速度 < LOW_VELOCITY → 15fps
   */
  _determineTargetFrameRate(velocity: number): number {
    const threshold = this._getThreshold();
    
    if (velocity >= threshold.HIGH_VELOCITY) {
      return this._frameRates.HIGH;
    } else if (velocity >= threshold.LOW_VELOCITY) {
      return this._frameRates.MID;
    } else {
      return this._frameRates.LOW;
    }
  }

  /**
   * 应用滞后逻辑，防止帧率频繁切换
   */
  _applyHysteresis(targetFrameRate: number): number {
    if (targetFrameRate === this._currentFrameRate) {
      this._stableCount = 0;
      return this._currentFrameRate;
    }
    
    // 升帧立即响应（保证流畅度）
    if (this._hysteresis.immediateUpgrade && 
        targetFrameRate > this._currentFrameRate) {
      this._currentFrameRate = targetFrameRate;
      this._stableCount = 0;
      this._updateSkipInterval();
      return this._currentFrameRate;
    }
    
    // 降帧需要连续多帧稳定（使用 > 确保 stableFramesRequired=0 时立即响应）
    this._stableCount++;
    if (this._stableCount > this._hysteresis.stableFramesRequired) {
      this._currentFrameRate = targetFrameRate;
      this._stableCount = 0;
      this._updateSkipInterval();
    }
    
    return this._currentFrameRate;
  }

  /**
   * 根据当前帧率更新跳帧间隔
   * 60fps → 跳帧间隔1（每帧渲染）
   * 30fps → 跳帧间隔2（每2帧渲染1次）
   * 15fps → 跳帧间隔4（每4帧渲染1次）
   */
  _updateSkipInterval(): void {
    this._skipInterval = Math.round(this._frameRates.HIGH / this._currentFrameRate);
  }

  /**
   * 计算最优帧率
   */
  calculateOptimalFrameRate(currentValue: number): number {
    const velocity = this._calculateVelocity(currentValue);
    const targetFrameRate = this._determineTargetFrameRate(velocity);
    return this._applyHysteresis(targetFrameRate);
  }

  /**
   * 判断当前帧是否应该渲染
   * 
   * @param currentValue 当前动画值
   * @returns 是否应该渲染此帧
   */
  shouldRenderFrame(currentValue: number): boolean {
    // 增加总帧数
    this._totalFrameCount++;
    
    // 保存旧的跳帧间隔
    const oldSkipInterval = this._skipInterval;
    
    // 更新帧率（基于当前值的变化速度）
    this.calculateOptimalFrameRate(currentValue);
    
    // 如果帧率切换了，强制渲染这一帧（避免视觉跳跃）
    if (this._skipInterval !== oldSkipInterval) {
      if (this._hysteresis.enableDebugLog) {
        console.log(`[FrameRate] 帧率切换: ${oldSkipInterval} → ${this._skipInterval}, fps=${this._currentFrameRate}, value=${currentValue.toFixed(2)}`);
      }
      this._frameCounter = 0;
      this._lastRenderValue = currentValue;
      return true;
    }
    
    // 正常跳帧逻辑
    this._frameCounter++;
    
    if (this._frameCounter >= this._skipInterval) {
      if (this._hysteresis.enableDebugLog) {
        const skippedFrames = this._skipInterval - 1;
        console.log(`[FrameRate] 渲染 | 跳过=${skippedFrames}帧 | fps=${this._currentFrameRate} | value=${currentValue.toFixed(2)} | velocity=${this._history?.velocity?.toFixed(1) ?? 'N/A'}`);
      }
      this._frameCounter = 0;
      this._lastRenderValue = currentValue;
      return true;
    }
    
    // 跳过帧
    if (this._hysteresis.enableDebugLog) {
      console.log(`[FrameRate] 跳过 | counter=${this._frameCounter}/${this._skipInterval} | fps=${this._currentFrameRate}`);
    }
    return false;
  }

  /**
   * 调度下一帧（始终使用 requestAnimationFrame）
   * 
   * 采用跳帧策略：
   * - 每帧都会调度 requestAnimationFrame
   * - 在回调中通过 shouldRenderFrame 判断是否真正渲染
   * - 确保动画时间准确，不会延长
   * 
   * @param callback 帧回调函数
   * @returns 帧标识符
   */
  scheduleNextFrame(callback: () => void): AnimationFrameID {
    // 始终使用 requestAnimationFrame，保证动画时间准确
    this._pendingFrame = requestAnimationFrame(callback);
    return this._pendingFrame;
  }

  /**
   * 取消待处理的帧
   */
  cancelPendingFrame(): void {
    if (this._pendingFrame !== null) {
      cancelAnimationFrame(this._pendingFrame);
      this._pendingFrame = null;
    }
  }

  /**
   * 获取当前帧率
   */
  getCurrentFrameRate(): number {
    return this._currentFrameRate;
  }

  /**
   * 获取当前跳帧间隔
   */
  getSkipInterval(): number {
    return this._skipInterval;
  }

  /**
   * 重置控制器状态
   */
  reset(): void {
    this._history = null;
    this._currentFrameRate = this._frameRates.HIGH;
    this._stableCount = 0;
    this._frameCounter = 0;
    this._skipInterval = 1;
    this._lastRenderValue = 0;
    this._totalFrameCount = 0;
    this.cancelPendingFrame();
  }
}
